/*******************************************************************
 *
 * Copyright (C), 2022-2027, YouGan, All rights reserved.
 *
 * Author      : zhaoyang
 * Create Time : 2022-08-10
 * Version     : v0.1
 * Description : 
 *******************************************************************/


#include <stdbool.h>
#include <stdint.h>
#include "nrf_log.h"
#include "ble_nus.h"
#include "data_handle.h"
#include "nrf_gpio.h"
#include "m_data_handle.h"
#include "w25q128.h"
#include "algo_distance.h"

#define UART_TX_SPEED_RT_MAX_CNT    10  //受限于uart的发送buf大小，每次最多发送实时速度数据条数设置上限

#pragma pack(1)
//蓝牙发送数据结构
typedef struct
{
    uint16_t    data_header;        //数据头，固定使用AACC
    uint8_t     data_type;          //数据类型：心率、跑步豆等
    uint8_t     reserved;           //保留字节
    uint32_t    data_len;           //数据长度
}BLE_TX_DATA_HEADER_T ;

//心率数据存储flash结构
typedef struct
{
    uint8_t     heart;          //心率值
    uint32_t    UTC;            //UTC时间
}HEART_DATA_FLASH_T ;
#pragma pack()

SPORTS_DATA_MANAGER_T g_his_data_manager_info = {0};    //flash历史数据管理信息，由于记录当前存储的数据条数、位置等信息

SPORTS_RT_DATA_MANAGER_T* pSports_rt_data = NULL;


SPORT_DATA_HIS_INFO_T g_sport_data = {0};

extern SPORT_DATA_T    g_sport_data_rt[SPORT_DATA_BUF_CNT];       //实时运动数据，全程记录，每秒刷新一次，每30s存储一次
extern uint8_t  g_sport_data_rt_index;     //实时速度数组下标

extern uint32_t ble_data_send(uint8_t* p_data, uint16_t p_length);

void mem_cpy (void* dst, const void* src, uint32_t cnt)
{
	uint8_t *d = (uint8_t*)dst;
	const uint8_t *s = (const uint8_t*)src;

	if (cnt)
	{
		do *d++ = *s++; while (--cnt);
	}
}

//*****************************************************************************
// * 函 数 名  : CheckSum
// * 函数功能  : 计算校验和
// * 输入参数  :	 
// *            src: 数据源
// *            lenth: 数据长度
// * 输出参数  : 无
// * 返 回 值  : 校验和
//*****************************************************************************/
void prepare_ble_sync_data(SPORT_DATA_T sport_data, uint16_t p_num)
{
    g_ble_sync_buf.header = 0xBBFF;
    g_ble_sync_buf.version = 0x10;
    g_ble_sync_buf.belt_id = g_sysmng_info.belt_id;
    g_ble_sync_buf.sync_id = g_sync_cmd_buf.sync_id;
    g_ble_sync_buf.packet_num = p_num;
    g_ble_sync_buf.heart_rate       = sport_data.u8heart;
    g_ble_sync_buf.data_len         = sizeof(g_ble_sync_buf.data);
    
    g_ble_sync_buf.data.total_distance      = sport_data.u16distance_total;
    g_ble_sync_buf.data.total_step          = sport_data.u16step_total;
    g_ble_sync_buf.data.total_calorie       = sport_data.u16cal;
    g_ble_sync_buf.data.pace                = sport_data.u8speed_rt;
    g_ble_sync_buf.data.step_frequency      = sport_data.u16step_fre_rt;
    g_ble_sync_buf.data.step_length         = sport_data.u8step_amplitude_rt;
    g_ble_sync_buf.data.heart_rate_interval = 0;    
    //g_ble_sync_buf.sync_data_cnt            = g_sync_cmd_buf.total_cnt;
    g_ble_sync_buf.sync_data_cnt            = g_sport_data.u32time_Sec - g_sync_total_cnt_finished;
}

//*****************************************************************************
// * 函 数 名  : CheckSum
// * 函数功能  : 计算校验和
// * 输入参数  :	 
// *            src: 数据源
// *            lenth: 数据长度
// * 输出参数  : 无
// * 返 回 值  : 校验和
//*****************************************************************************/

uint32_t CheckSum(uint8_t *src, uint16_t lenth)
{
    uint32_t sum = 0;
    for(uint16_t i = 0; i < lenth; i++)
    {
        sum += src[i];
    }
    
    return sum;
}

//*****************************************************************************
// * 函 数 名  : his_data_manage_init
// * 函数功能  : 历史数据管理信息初始化，从flash恢复当前存储的历史数据信息
// * 输入参数  :	 无
// * 输出参数  : 无
// * 返 回 值  : 无
//*****************************************************************************/
void his_data_manage_init(void)
{
    NRF_LOG_INFO("his_data_manage_init");

    uint32_t u32checksum = 0;

    //从flash恢复当前存储的历史数据信息
    Flash_Read((uint8_t*)&g_his_data_manager_info, SPI_FLASH_DATA_MANAGER_ADDR_START, sizeof(g_his_data_manager_info));

    //根据校验和检查数据是否有效
    u32checksum = CheckSum((uint8_t*)&g_his_data_manager_info, (sizeof(g_his_data_manager_info) - 4));

    if ((u32checksum != g_his_data_manager_info.checksum) || (0xAACC != g_his_data_manager_info.u16init_flag))
    {
        memset((uint8_t*)&g_his_data_manager_info, 0, sizeof(g_his_data_manager_info));
        g_his_data_manager_info.u16init_flag = 0xAACC;

        //最好擦除一次本区域flash
    }

    pSports_rt_data = &g_his_data_manager_info.rt_data;
    
    //初始化高斯滤波参数
    Gauss_para_init();

    //主控MCU请求发送数据检测pin
//    nrf_gpio_cfg_input(MCU_CS_PIN, NRF_GPIO_PIN_PULLDOWN);
    
//    nrf_delay_ms(10);
}

//*****************************************************************************
// * 函 数 名  : his_data_manage_save
// * 函数功能  : 写数据管理信息到flash
// * 输入参数  :	 无
// * 输出参数  : 无
// * 返 回 值  : 无
//*****************************************************************************/
void his_data_manage_save(void)
{
    //计算校验和
    g_his_data_manager_info.checksum =  CheckSum((uint8_t*)&g_his_data_manager_info, (sizeof(g_his_data_manager_info) - 4));

    //先删除flash中的数据，最小删除单位sector 4K
    Flash_Erase_Sector(SPI_FLASH_DATA_MANAGER_ADDR_START);

    //写当前的数据到flash
    Flash_Write((uint8_t*)&g_his_data_manager_info, SPI_FLASH_DATA_MANAGER_ADDR_START, sizeof(g_his_data_manager_info));
}

//*****************************************************************************
// * 函 数 名  : sport_data_sum_save_flash
// * 函数功能  : 汇总运动数据存储到flash
// * 输入参数  :	 无
// * 输出参数  : 无
// * 返 回 值  : 无
//*****************************************************************************/
void sport_data_sum_save_flash(void)
{
    uint32_t addr_write         = 0;
    uint32_t u32Single_data_len = sizeof(g_sport_data);   //单条记录长度

    uint32_t data_len           = 0;    //待写数据总长度

    //先根据偏移计算当前要写入flash的地址
    uint8_t u8wirte_index = g_his_data_manager_info.u8his_cnt;
    addr_write = SPI_FLASH_SPORT_DATA_ADDR_START + u8wirte_index * u32Single_data_len;

    //要写入数据长度
    data_len = u32Single_data_len;

    //为确保写成功，需要写新的sector时先删除sector数据
    if (0 == (addr_write % 4096))
    {
        //删除当前sector
        Flash_Erase_Sector(addr_write);
    }
    else if ((addr_write + data_len - 1) % 4096 < data_len)
    {
        //删除下一sector
        Flash_Erase_Sector((addr_write + data_len - 1));
    }

    //写当前的数据到flash
    Flash_Write((uint8_t*)&g_sport_data, addr_write, data_len);

}


//*****************************************************************************
// * 函 数 名  : sports_data_rt_save_flash
// * 函数功能  : 存储实时运动（实时速度）数据到flash
// * 输入参数  :	 无
// * 输出参数  : 无
// * 返 回 值  : 无
//*****************************************************************************/
void sports_data_rt_save_flash(void)
{
    NRF_LOG_INFO("sports_data_rt_save_flash: %d", g_sport_data_rt_index);

    uint32_t addr_write         = 0;
    uint32_t u32Single_data_len = sizeof(SPORT_DATA_T);   //单条记录长度

    uint32_t data_len           = 0;    //待写数据总长度
//    uint32_t write_len          = 0;    //当前写数据长度

    if (NULL == pSports_rt_data)
    {
        pSports_rt_data = &g_his_data_manager_info.rt_data;
    }

    //先根据偏移计算当前要写入flash的地址
    addr_write = SPI_FLASH_SPEED_RT_DATA_ADDR_START + pSports_rt_data->cur_offset;

    //要写入数据长度
    data_len = g_sport_data_rt_index * u32Single_data_len;

    //为确保写成功，需要写新的sector时先删除sector数据
    if (0 == (addr_write % 4096))
    {
        //删除当前sector
        Flash_Erase_Sector(addr_write);
    }
    else if ((addr_write + data_len - 1) % 4096 < data_len)
    {
        //删除下一sector
        Flash_Erase_Sector((addr_write + data_len - 1));
    }

    //写当前的数据到flash
    Flash_Write((uint8_t*)g_sport_data_rt, addr_write, data_len);

    //更新管理信息
    pSports_rt_data->cur_offset += data_len;


    //更新管理信息
    pSports_rt_data->total_cnt += g_sport_data_rt_index;

    g_sport_data_rt_index = 0;
}


//*****************************************************************************
// * 函 数 名  : sports_data_rt_upload
// * 函数功能  : 存储flash的实时速度数据上传
// * 输入参数  :	 u8index
// * 输出参数  : 无
// * 返 回 值  : 无
//*****************************************************************************/
void sports_data_rt_upload(uint8_t u8index)
{
    NRF_LOG_INFO("sports_data_rt_upload");
    SPORT_DATA_HIS_INFO_T sport_his_data = {0};
    
    uint8_t tx_data_buf[244]    = {0};
    uint16_t u16length          = 0;

    uint16_t u16data_cnt        = 0;
    
    uint8_t read_cnt            = 0;

    uint32_t u32addr            = 0;
    
    uint32_t u32Single_data_len = sizeof(SPORT_DATA_T);   //单条实时速度记录长度
    uint32_t u32Single_his_data_len = sizeof(SPORT_DATA_HIS_INFO_T);   //单条历史记录长度

    //超过范围
    if (u8index >= HIS_DATA_CNT_MAX)
    {
        return;
    }

    //要发送的记录条数和存储地址
    if(g_sync_cmd_buf.total_cnt == 0)
    {
        //存储课程为空
        if (0 == g_his_data_manager_info.u8his_cnt)
        {
            return;
        }
        //从flash读取第一条历史数据记录信息
        u32addr   = SPI_FLASH_SPORT_DATA_ADDR_START + u8index * u32Single_his_data_len;
        Flash_Read((uint8_t*)&sport_his_data, u32addr, u32Single_his_data_len);
        u16data_cnt = sport_his_data.sports_rt_info.u16speed_rt_cnt - (g_sync_addr - 0xD02000)/sizeof(SPORT_DATA_T);
        //u32addr = sport_his_data.sports_rt_info.u32addr_start + SPI_FLASH_SPEED_RT_DATA_ADDR_START;
        u32addr  = g_sync_addr;
        
        NRF_LOG_INFO("u32addr=0x%x",u32addr);//0xD02000
    }
    else
    {
        u16data_cnt = g_sync_cmd_buf.total_cnt;
        u32addr  = g_sync_addr;
    }
   
	SPORT_DATA_T m_sport_data_read;
	uint8_t ble_send_buff[260];   //发送buff
	uint16_t packet_n =0;    //包序号
    
    NRF_LOG_INFO("u16data_cnt=%d",u16data_cnt);
    
    g_sync_cmd_buf.total_cnt = u16data_cnt;
    //上传flash中的数据
    while (u16data_cnt)
    {
	    if(!sync_flag)//启动数据同步
		{
			return;
		}
        
        //从flash中读取心率数据，每次最多读取10条进行发送
        if (u16data_cnt >= UART_TX_SPEED_RT_MAX_CNT)
        {
            read_cnt    = UART_TX_SPEED_RT_MAX_CNT;
            u16data_cnt -= UART_TX_SPEED_RT_MAX_CNT;
        }
        else
        {
            read_cnt    = u16data_cnt;
            u16data_cnt = 0;
        }
        NRF_LOG_INFO("read_cnt=%d",read_cnt);//每次发送同步数据数量
        
        //从flash读取数据信息
        u16length = u32Single_data_len * read_cnt;
    
        Flash_Read(tx_data_buf, u32addr, u16length);
        u32addr += u16length;
#if 1
	    //处理10包数据
	    for(int i = 0 ; i < read_cnt ; i++)
	    {
		    memcpy(&m_sport_data_read , (tx_data_buf + i*u32Single_data_len), u32Single_data_len);
            prepare_ble_sync_data(m_sport_data_read , ++packet_n);
		    memcpy(ble_send_buff + i*g_ble_sync_buf_size , (const void*)&g_ble_sync_buf , g_ble_sync_buf_size);
	    }
	    //ble发送
	    ble_data_send(ble_send_buff , read_cnt * g_ble_sync_buf_size);
	    memset(ble_send_buff , 0 , sizeof(ble_send_buff));
#endif
    }
#if 1
		sync_flag = 0;
        m_bracelet_state.pe_state=4; //转为"同步完成"
        g_sync_cmd_buf.total_cnt = 0;
#endif		

}

//*****************************************************************************
// * 函 数 名  : sports_data_rt_del
// * 函数功能  : 按索引删除flash数据，只允许一次删除所有
// * 输入参数  :	 u8index
// * 输出参数  : 无
// * 返 回 值  : 无
//*****************************************************************************/
void sports_his_data_del(void)
{
    //删除flash中的汇总运动数据，最小删除单位sector 4K
    Flash_Erase_Sector(SPI_FLASH_SPORT_DATA_ADDR_START);

    for (uint16_t i = 0; i < SPI_FLASH_SPEED_RT_DATA_SIZE/4096; i++)
    {
        //删除flash中的实时运动数据，最小删除单位sector 4K
        Flash_Erase_Sector(SPI_FLASH_SPEED_RT_DATA_ADDR_START + i*4096);
    }

    //更新管理信息
    g_his_data_manager_info.u8his_cnt = 0;
    g_his_data_manager_info.rt_data.cur_offset = 0;
    g_his_data_manager_info.rt_data.total_cnt = 0;

    pSports_rt_data->cur_offset      = 0;
    pSports_rt_data->total_cnt       = 0;
    
    his_data_manage_save();
}


void uart_test(void)
{
    static uint16_t timer_cnt = 0;
    
    timer_cnt++;
    
    if (timer_cnt > 30)
    {
//        heart_data_upload();
    }

}


